package com.fuyun.microservice.codec;

import com.fuyun.microservice.codec.msg.Header;
import com.fuyun.microservice.codec.msg.Message;
import com.fuyun.microservice.utils.BufferUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;
import org.apache.coyote.http2.ByteUtil;

import java.util.List;

@Slf4j
@ChannelHandler.Sharable
public class HeaderCodec extends MessageToMessageCodec<ByteBuf, Message> {
    private final static byte[] emptyBytes = new byte[0];
    public final static short HEADER_LENGTH = 12;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) {
        //此时已处理过粘包和断包了，bytebuf里是完整的一帧
        Header header = new Header();
        header.setBodyLength(bytebuf.readShort());
        header.setCommandId(bytebuf.readShort());
        header.setSequenceNo(bytebuf.readLong());

        Message message = new Message();
        if (header.getBodyLength() > HEADER_LENGTH) {
            int contentLength = header.getBodyLength() - HEADER_LENGTH;
            byte[] bodyBuffer = BufferUtil.toByteArraySafe(bytebuf.readBytes(contentLength));
            message.setBodyBuffer(bodyBuffer);
        } else {
            message.setBodyBuffer(emptyBytes);
        }
        message.setHeader(header);
        list.add(message);
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Message message, List<Object> list) {
        short bodyLength = (short) (message.getBodyBuffer().length + HEADER_LENGTH);

        // buf由netty写channel的时候释放
        ByteBuf buf = ctx.alloc().buffer(bodyLength);
        buf.writeShort(bodyLength);
        buf.writeShort(message.getHeader().getCommandId());
        buf.writeLong(message.getHeader().getSequenceNo());
        if (bodyLength > HEADER_LENGTH) {
            buf.writeBytes(message.getBodyBuffer());
        }

        log.debug("WRITE: {}B\n{}", buf.readableBytes(),ByteBufUtil.prettyHexDump(buf));
        list.add(buf);
    }

}
